package com.zhang.crowd.handler;

import com.zhang.crowd.api.MySQLRemoteService;
import com.zhang.crowd.api.RedisRemoteService;
import com.zhang.crowd.config.ShortMessageProperties;
import com.zhang.crowd.constant.CrowdConstant;
import com.zhang.crowd.entity.po.MemberPO;
import com.zhang.crowd.entity.vo.MemberLoginVO;
import com.zhang.crowd.entity.vo.MemberVO;
import com.zhang.crowd.util.CrowdUtil;
import com.zhang.crowd.util.ResultEntity;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;
import java.util.Objects;
import java.util.concurrent.TimeUnit;



@Controller
public class MemberHandler {
    @Autowired
    private ShortMessageProperties shortMessageProperties;

    @Autowired
    private RedisRemoteService redisRemoteService;

    @Autowired
    private MySQLRemoteService mySQLRemoteService;

    @RequestMapping("/auth/member/logout")
    public String logout(HttpSession session){
        session.invalidate();
        return "redirect:/";
    }



    @RequestMapping("/auth/member/do/login")
    public String doLogin(
            @RequestParam("loginacct") String loginacct,
            @RequestParam("userpswd") String userpswd,
            ModelMap modelMap,
            HttpSession session
            ){
        ResultEntity<MemberPO> resultEntity = mySQLRemoteService.getMemberPOByLoginAcctRemote(loginacct);

        if(ResultEntity.FAILED.equals(resultEntity.getResult())){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,resultEntity.getMessage());

            return "member-login";
        }

        MemberPO memberPO = resultEntity.getData();

        if(memberPO == null){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }
        String userpswdDataBase = memberPO.getUserpswd();
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

        boolean macherResult = passwordEncoder.matches(userpswd, userpswdDataBase);

        if(!macherResult){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }
        // 创建MemberLoginVO对象存入Session域
        MemberLoginVO memberLoginVO = new MemberLoginVO(memberPO.getId(),memberPO.getUsername(), memberPO.getEmail());
        session.setAttribute(CrowdConstant.ATTR_NAME_LOGIN_MEMBER,memberLoginVO);

        return "redirect:http://www.crowd.com/auth/member/to/center/page";
    }


    @RequestMapping("/auth/do/member/register")
    public String register(MemberVO memberVO, ModelMap modelMap){
        // 1、获取用户输入的手机号
        String phoneNum = memberVO.getPhoneNum();

        // 2、拼Redis中存储验证码的Key
        String key = CrowdConstant.REDIS_CODE_PREFIX + phoneNum;

        // 3、从Redis读取Key对应的value
        ResultEntity<String> resultEntity = redisRemoteService.getRedisStringValueByKeyRemote(key);

        // 4、检查查询操作是否有效
        String result = resultEntity.getResult();
        if(ResultEntity.FAILED.equals(result)){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,resultEntity.getMessage());
            return "member-reg";
        }

        String redisCode = resultEntity.getData();

        if(redisCode == null){
            modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_CODE_NOT_EXISTS);
            return "member-reg";
        }

            // 5、如果从Redis能够查询到Value则比较表单验证码和Redis验证码
            String formCode = memberVO.getCode();

            if(!Objects.equals(formCode,redisCode)){
               modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,CrowdConstant.MESSAGE_CODE_INVALIDE);
               return "member-reg";
            }


                // 6、如果验证码一致，则从Redis删除
                redisRemoteService.removeRedisKeyRemote(key);

                // 7、执行密码加密
                BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
                String userpswdBeforeEncode = memberVO.getUserpswd();

                String userpswdAfterEncode = passwordEncoder.encode(userpswdBeforeEncode);

                memberVO.setUserpswd(userpswdAfterEncode);

                // 8、执行保存
                //创建空的MemberPO对象
                MemberPO memberPO = new MemberPO();

                //复制属性
                BeanUtils.copyProperties(memberVO,memberPO);

                //调用远程方法
                ResultEntity<String> saveMemberResultEntity = mySQLRemoteService.saveMember(memberPO);
                if(ResultEntity.FAILED.equals(saveMemberResultEntity.getResult())){
                    modelMap.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE,saveMemberResultEntity.getMessage());
                    return "member-reg";
                }
        //使用重定向是避免刷新浏览器导致重新执行注册流程
        return "redirect:/auth/member/to/login/page";
    }

    @ResponseBody
    @RequestMapping("/auth/member/send/short/message.json")
    public ResultEntity<String> sendMessage(@RequestParam("phoneNum") String phoneNum){

        // 1.发送验证码到phoneNum手机
        ResultEntity<String> sendMessageResultEntity = CrowdUtil.sendShortMessage(
                shortMessageProperties.getHost(),       //主机地址
                shortMessageProperties.getPath(),       //请求路径
                shortMessageProperties.getMethod(),     //请求方式
                phoneNum,                               //用户手机号
                shortMessageProperties.getAppCode(),    //三方接口的AppCode
                shortMessageProperties.getSign(),       //三方接口的签名，（没有使用）
                shortMessageProperties.getTemplate_id() //三方接口信息的模板（这里使用的是默认的）
        );
        // 2.判断短信发送结果
        if(ResultEntity.SUCCESS.equals(sendMessageResultEntity.getResult())){
            // 3.如果发送成功,则将验证码存入Redis
            // 从上一步的操作中获取随机生成的验证码
            String code = sendMessageResultEntity.getData();
            //拼接一个用于在Redis中存储数据的Key
            String key = CrowdConstant.REDIS_CODE_PREFIX + phoneNum;
            //调用远程接口存入Redis
            ResultEntity<String>  saveCodeResultEntity = redisRemoteService.setRedisKeyValueRemoteWithTimeout(key, code,3, TimeUnit.MINUTES);
            //判断结果
            if(ResultEntity.SUCCESS.equals(saveCodeResultEntity.getResult())){
                return ResultEntity.successWithoutData();
            }else{
                return saveCodeResultEntity;
            }
        }else {
            return sendMessageResultEntity;
        }
    }
}
